package xj.graph2d;

import static xj.graph2d.DrawShapeConstants.WRITE_XML_TEMPLATE;
import static xj.graph2d.DrawShapeConstants.d;

import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import xj.lang.CodeWriter;

public class CompoundDrawShape extends DrawShapeBase {

  public CompoundDrawShape() {
    atomic = false;
    allowRotation = false;
    subshapes = new ArrayList<DrawShape>();
  }

  public DrawShape makeInstance() {
    return new CompoundDrawShape();
  }

  @Override
  public boolean isCompound() {
    return true;
  }

  @Override
  public void setSelectedSubShape(DrawShape s) {
    deselectShape();
    selectedSubshape = s;
  }

  public void deselectShape() {
    if (selectedSubshape != null && 
	selectedSubshape instanceof CompoundDrawShape) {
      CompoundDrawShape container = (CompoundDrawShape) selectedSubshape;
      container.deselectShape();
    }
    selectedSubshape = null;
  }

  public DrawShapeSearch.Result search(Point2D p) {
    DrawShapeSearch.Result result = null;
    if (p != null) {
      DrawShape shape;
      int pos = DrawShapeConstants.PointOutside;
      int n = subshapes.size();
      for (int i = n - 1; i >= 0; i--) {
	shape = subshapes.get(i);
	if (shape != null && 
	    shape.isSearchable()) {
	  pos = shape.isInside(p);
	  if (pos != DrawShapeConstants.PointOutside) {
	    if (shape instanceof CompoundDrawShape && !shape.isAtomic()) {
	      result = ((CompoundDrawShape) shape).search(p);
	    }
	    if (result == null) {
	      result = new DrawShapeSearch.Result(shape, pos);
	    }
	    break;
	  }
	}
      }
    }
    return result;
  }

  @Override
  public void draw(Graphics2D g2) {
    // drawSubShapes(g2, DRAW_DEFAULT, null);
  }

  @Override
  public void adjustBounds() {
  }

  @Override
  public void calculateBounds() {
    fitComponents();
    //System.out.println("CompoundDrawShape.calculateBounds() bounds=" + getBoundsString());
    //framebounds.setRect(bounds.getX() - d, bounds.getY() - d, 
    //			bounds.getWidth() + 2 * d, bounds.getHeight() + 2 * d);
  }

  @Override
  public String toString() {
    StringBuilder buf = new StringBuilder();
    int n = subshapes.size();
    for (int i = 0; i < n; i++) {
      DrawShape shape = subshapes.get(i);
      buf.append("[" + i + "] " + shape.toString() + "\n");
    }
    return (super.toString() + "\n" + "  Compound size=" + n + "\n" + buf);
  }

  @Override
  public void layoutComponents() {
    fitComponents();
  }

  @Override
  public void componentMoved(DrawShape comp, float dx, float dy) {
    if (comp != null) {
      int n = subshapes.size();
      for (int i = 0; i < n; i++) {
	DrawShape shape = subshapes.get(i);
	if (shape != comp) {
	  shape.move(dx, dy);
	}
      }
      p1.setLocation((float) p1.getX() + dx, (float) p1.getY() + dy);
      p2.setLocation((float) p2.getX() + dx, (float) p2.getY() + dy);
      calculateBounds();
      if (parent.isFitted()) {
	parent.componentMoved(this, dx, dy);
      }
    }
  }

  @Override
  protected void writeXMLElements(CodeWriter out, int mode,
				  String namespacePrefix) {
    if (out != null) {
      super.writeXMLElements(out, mode, namespacePrefix);

      if (mode != WRITE_XML_TEMPLATE || !isAtomic()) {
	writeXMLSubShapes(out, mode, namespacePrefix);
      }
    }
  }

  protected static final boolean debug = false;

}
